package com.apes.hr.group.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.hr.group.model.DingDingPerson;
import com.apes.hr.group.repository.DingDingPersonRepository;
import com.apes.hr.recruit.model.ApplyJobOrder;
import com.apes.hr.recruit.repository.ApplyJobOrderRepository;
import com.apes.hr.thirdParty.dingidng.model.DingDingToken;
import com.apes.hr.transfer.model.TransferApplication;
import com.apes.hr.transfer.model.TransferApplicationItem;
import com.apes.hr.transfer.repository.TransferApplicationRepository;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiDepartmentListRequest;
import com.dingtalk.api.request.OapiUserGetDeptMemberRequest;
import com.dingtalk.api.request.OapiUserGetRequest;
import com.dingtalk.api.response.OapiDepartmentListResponse;
import com.dingtalk.api.response.OapiUserGetDeptMemberResponse;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.taobao.api.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 功能：钉钉人员关联erp人员
 *
 * @author ZhengZX
 * @create 2020年11月23日10:50:24
 */
@Service("hrDingDingPersonService")
public class DingDingPersonService extends DomainService {

    @Autowired
    DingDingToken dingDingToken;
    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    DingDingPersonRepository dingDingPersonRepository;
    @Autowired
    DingDingDeptService dingDingDeptService;
    @Autowired
    ApplyJobOrderRepository applyJobOrderRepository;
    @Autowired
    TransferApplicationRepository transferApplicationRepository;
    @Autowired
    private ApesLoggerService apesLoggerService;

    /**
     * 获取企业全部员工的钉钉userID
     * @return
     */
    public List<String> getFirmAllEmployee(){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list");
        OapiDepartmentListRequest req = new OapiDepartmentListRequest();
        req.setId("1");
        OapiDepartmentListResponse rsp = null;
        try {
            rsp = client.execute(req, dingDingToken.getAccessToken());
        } catch (ApiException e) {
            e.printStackTrace();
        }
        List<OapiDepartmentListResponse.Department> department = rsp.getDepartment();
        List<String> userIds = new ArrayList<>();
        department.stream().forEach(d -> {
            DingTalkClient client2 = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getDeptMember");
            OapiUserGetDeptMemberRequest req2 = new OapiUserGetDeptMemberRequest();
            req2.setDeptId(String.valueOf(d.getId()));
            try {
                OapiUserGetDeptMemberResponse rsp2 = client2.execute(req2, dingDingToken.getAccessToken());
                if (rsp2.getErrcode()==0){
                    userIds.addAll(rsp2.getUserIds());
                }
            } catch (ApiException e) {
                e.printStackTrace();
            }
        });
        return userIds;
    }

    /**
     * 根据钉钉工号同步erp钉钉ID
     */
    public String  syncDingDingUserIdToErpByJobNumber(){
        List<String> userIds = getFirmAllEmployee();
        userIds = userIds.stream().distinct().collect(Collectors.toList()); //去除重复员工数据
        AtomicInteger count = new AtomicInteger();  //记录操作数量
        userIds.stream().forEach(id ->{
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
            OapiUserGetRequest req = new OapiUserGetRequest();
            req.setUserid(id);    //根据ID获取信息
            try {
                OapiUserGetResponse rsp = client.execute(req, dingDingToken.getAccessToken());
                if (rsp.getErrcode() == 0){
                    Employee employee = employeeRepository.findByOrigin(rsp.getJobnumber());//根据钉钉的工号查找对应的人员信息
                    String dingDingUserId = rsp.getUserid();    //获取钉钉ID
                    if (employee!=null){
                        DingDingPerson dingDingPerson = dingDingPersonRepository.findByEmployee(employee);  //查找系统是否已经存在
                        if (dingDingPerson!=null){
                            if (!dingDingPerson.getDingDingUserId().equals(dingDingUserId)){   //和原来的存储不一致进行修改
                                dingDingPerson.setDingDingUserId(dingDingUserId);
                                dingDingPersonRepository.saveAndFlush(dingDingPerson);
                                count.addAndGet(1);
                            }
                        }else {
                            DingDingPerson dingPerson = new DingDingPerson();
                            dingPerson.setEmployee(employee);
                            dingPerson.setDingDingUserId(dingDingUserId);
                            dingDingPersonRepository.saveAndFlush(dingPerson);
                            count.addAndGet(1);
                        }
                    }
                }
            } catch (ApiException e) {
                e.printStackTrace();
            }
        });
        return "修改了[" + count.get() + "]名人员的钉钉ID";
    }

    /**
     * 根据钉钉ID查找对应人员
     * @param userId 钉钉UserId
     * @return employee
     */
    public Employee findByDingDingUserId(String userId){
        DingDingPerson dingDingPerson =dingDingPersonRepository.findOne(JpaDsl.toCriteriaByEq(
                "dingDingUserId", userId
        )).orElse(null);
        Employee employee = null;
        if (dingDingPerson!=null) employee = dingDingPerson.getEmployee();
        return employee;
    }

    /**
     * 更新全部人员钉钉职位信息(使用工作部门加岗位) 21.04.14
     */
    public String updatePosition(){
        List<DingDingPerson> persons = dingDingPersonRepository.findAll();
        int size = persons.size();
        AtomicInteger count = new AtomicInteger();  //记录操作数量
        persons.stream().forEach(person -> {
            dingDingDeptService.updateDingDingUserPosition(person.getEmployee().getWorkBranch().getName() + "【" + person.getEmployee().getPost().getName() + "】",person.getDingDingUserId());
            count.addAndGet(1);
        });
        return "一共有" + size + " 名钉钉人员，成功更新信息" + count + " 名";
    }

    /**
     * 修改，目前仅支持修改钉钉ID
     * @param request
     * @return
     */
    public DingDingPerson update(SimpleRequest request){
        DingDingPerson dingDingPerson = request.getO(DingDingPerson.class);
        return dingDingPersonRepository.saveAndFlush(dingDingPerson);
    }

    /**
     * 系统人员手动同步钉钉后台
     * @param request
     * @return
     */
    public DingDingPerson sync(SimpleRequest request){
        DingDingPerson dingDingPerson = request.getO(DingDingPerson.class);
        if (dingDingPerson.getEntryId() == null && dingDingPerson.getTransferId() == null) throw new RuntimeException("请输入入职申请单号或者调动申请单号才可以对人员进行同步");
        if (!dingDingPerson.getDeptSign() && !dingDingPerson.getGroupSign()) throw new RuntimeException("请选择同步人员钉钉部门群还是同步钉钉考勤组!!!");
        String dingDingUserId = dingDingPerson.getDingDingUserId();
        if (dingDingPerson.getEntryId() != null){
            ApplyJobOrder applyJobOrder = applyJobOrderRepository.findOne(dingDingPerson.getEntryId());
            if (applyJobOrder == null) throw new RuntimeException("入职申请单号" + dingDingPerson.getEntryId() + "未查询到！！！");
            if (dingDingPerson.getDeptSign()){
                List<Long> ids = dingDingDeptService.getDingDingIds(applyJobOrder.getCompany().getParty().getCorporate().getOperation(),
                        applyJobOrder.getCompany(), applyJobOrder.getBranch(), applyJobOrder.getWorkPost());
                //更新人员钉钉群组
                dingDingDeptService.userUpdate(ids,dingDingUserId);
                //写入日志
                insertLogger(dingDingPerson.getId(),"手动根据入职申请单号" + applyJobOrder.getId() +"同步人员钉钉部门",request.getSession().getUserId());
                //如果入职的员工岗位是店长或者店长（驻店股东）设置为入职部门群的主管
                if (applyJobOrder.getWorkPost().getId().equals("0000016") || applyJobOrder.getWorkPost().getId().equals("0000752")){
                    List<Long> branchDingDing = dingDingDeptService.getBranchDingDing(applyJobOrder.getBranch());   //根据部门获取对应的钉钉群
                    for (Long b : branchDingDing) {
                        String zgByDept = dingDingDeptService.getZGByDept(String.valueOf(b));   //获取该部门主管
                        if (!zgByDept.equals("")) {
                            //此入职员工非该部门的主管拼接
                            if (!zgByDept.contains(dingDingUserId)) {
                                zgByDept = zgByDept + "|" + dingDingUserId;
                                dingDingDeptService.updateDeptByZG(b, zgByDept);//执行更新部门主管操作
                            }
                        }
                        if (zgByDept.equals("")) dingDingDeptService.updateDeptByZG(b,dingDingUserId);  //部门主管列表为空直接更新当前入职员工为钉钉部门主管
                    }
                };
            }
            if (dingDingPerson.getGroupSign()){
                //更新人员考勤组
                String groupId = dingDingDeptService.findGroupByBranchOrEmployee(applyJobOrder.getEmployee(), applyJobOrder.getBranch());
                if (Objects.isNull(groupId)) throw new RuntimeException("根据行政部门" + applyJobOrder.getBranch().getName() + "没有找到对应的考勤组，请检查钉钉考勤组规则！！！");
                dingDingDeptService.updateUserGroup(groupId,dingDingUserId);
                //写入日志
                insertLogger(dingDingPerson.getId(),"手动根据入职申请单号" + applyJobOrder.getId() +"同步人员钉钉考勤组",request.getSession().getUserId());
            }
        }else if(dingDingPerson.getTransferId() != null){
            TransferApplication application = transferApplicationRepository.findOne(dingDingPerson.getTransferId());
            if (application == null) throw new RuntimeException("调动申请单号" + dingDingPerson.getEntryId() + "未查询到！！！");
            TransferApplicationItem item =  application.getTransferApplicationItems().stream().filter(transferApplicationItem ->
                    transferApplicationItem.getTransferUid().getId().equals(dingDingPerson.getEmployee().getId())).findFirst().get();
            if (dingDingPerson.getDeptSign()){
                //根据调动单的运营模式公司部门岗位信息查找对应的钉钉部门
                List<Long> ids = dingDingDeptService.getDingDingIds(item.getTransferUid().getCompany().getParty().getCorporate().getOperation(),
                        item.getTransferUid().getCompany(), item.getBranchAfter(), item.getWorkPostAfter());
                //更新人员钉钉群组
                dingDingDeptService.userUpdate(ids,dingDingUserId);
                //写入日志
                insertLogger(dingDingPerson.getId(),"手动根据调动申请单号" + application.getId() +"同步人员钉钉部门",request.getSession().getUserId());
                //员工调动后的岗位是店长或者店长（驻店股东）设置为调动后部门群的主管
                if (item.getWorkPostAfter().getId().equals("0000016") || item.getWorkPostAfter().getId().equals("0000752")){
                    List<Long> branchDingDing = dingDingDeptService.getBranchDingDing(item.getBranchAfter());   //根据部门获取对应的钉钉群
                    for (Long b : branchDingDing) {
                        String zgByDept = dingDingDeptService.getZGByDept(String.valueOf(b));
                        if (!zgByDept.equals("")){
                            //根据主管列表判断当前的ID是否已经存在（存在为已经是主管的情况） 取反结果集为不存在的情况
                            if (!(zgByDept.contains("|" + dingDingUserId) || zgByDept.contains(dingDingUserId + "|") || zgByDept.contains(dingDingUserId))){
                                dingDingDeptService.updateDeptByZG(b,zgByDept + "|" + dingDingUserId);
                            }
                        }
                        if (zgByDept.equals("")) dingDingDeptService.updateDeptByZG(b,dingDingUserId);//执行更新部门主管操作 (当前更新的部门没有主管情况下直接将当前人更新为主管)
                    }
                }
                //员工调动前的岗位是店长或者店长（驻店股东） 调动后的岗位非店长或者店长（驻店股东）取消当前部门群的主管 (降职情况)
                if ((item.getWorkPost().getId().equals("0000016")&&!item.getWorkPostAfter().getId().equals("0000016")) ||
                        (item.getWorkPost().getId().equals("0000752")&&!item.getWorkPostAfter().getId().equals("0000752")) ) {
                    List<Long> branchDingDing = dingDingDeptService.getBranchDingDing(item.getBranch());   //根据部门获取对应的钉钉群
                    branchDingDing.forEach(b -> {
                        String zgByDept = dingDingDeptService.getZGByDept(String.valueOf(b));
                        if (!zgByDept.equals("")) {    //获取该部门的主管列表不为空 剔除当前员工在部门群的主管
                            if (zgByDept.contains("|" + dingDingUserId)) {
                                zgByDept = zgByDept.replaceAll("\\|" + dingDingUserId, "");
                            } else if (zgByDept.contains(dingDingUserId + "|")) {
                                zgByDept = zgByDept.replaceAll(dingDingUserId + "\\|", "");
                            } else if (zgByDept.contains(dingDingUserId)) {
                                zgByDept = zgByDept.replaceAll(dingDingUserId, "");
                            }
                        }
                        if (zgByDept.equals("")) zgByDept = "|"; //如果zgByDept 为空说明剔除或本身获取就是空，需要传 一个 | 清空该部门的主管
                        dingDingDeptService.updateDeptByZG(b, zgByDept);//执行更新部门主管操作
                    });
                }
            }
            if (dingDingPerson.getGroupSign()){
                //更新人员考勤组
                String groupId = dingDingDeptService.findGroupByBranchOrEmployee(item.getTransferUid(), item.getBranchAfter());
                if (Objects.isNull(groupId)) throw new RuntimeException("根据行政部门" + item.getBranchAfter().getName() + "没有找到对应的考勤组，请检查钉钉考勤组规则！！！");
                dingDingDeptService.updateUserGroup(groupId,dingDingUserId);
                //写入日志
                insertLogger(dingDingPerson.getId(),"手动根据调动申请单号" + application.getId() +"同步人员钉钉考勤组",request.getSession().getUserId());
            }
        }
        return dingDingPerson;
    }

    /**
     * 日志插入
     */
    public void insertLogger(String businessKey,String operate,String operator_id){
        apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                "businessKey", businessKey, "operate", operate, "workPostName",null,"operator_id", operator_id));
    };
}
